﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.IO;
using System.Drawing.Imaging;
using Microsoft.Win32;

namespace PcBackgroundMgr.Controls
{

    /// <summary>
    /// ImageCutor.xaml 的交互逻辑
    /// </summary>
    public partial class ImageCutor : Window
    {
        #region 成员变量

        private Point previousMousePoint;
        private bool isMouseLeftButtonDown;
        private Cursor oldCursor;
        private IMAdorner _IMAdorner;

        public System.Drawing.Image ResultImage { get; set; }

        #endregion 成员变量

        #region 成员方法

        public void SetImage(string filePath)
        {
            // Read byte[] from png file
            BinaryReader binReader = new BinaryReader(File.Open(filePath, FileMode.Open));
            FileInfo fileInfo = new FileInfo(filePath);
            byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);
            binReader.Close();

            // Init bitmap
            BitmapImage bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.StreamSource = new MemoryStream(bytes);
            bitmap.EndInit();

            this.MasterImage.Source = bitmap;
            this.filePath = filePath;
            this.ResultImage = null;
        }

        public static bool GetPicThumbnail(System.Drawing.Image iSource, string outPath, int flag)
        {
            ImageFormat tFormat = iSource.RawFormat;

            //以下代码为保存图片时，设置压缩质量  
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100  
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    iSource.Save(outPath, jpegICIinfo, ep);//dFile是压缩后的新路径  
                }
                else
                {
                    iSource.Save(outPath, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                iSource.Dispose();
            }
        }

        //C#快速获取JPG图片大小及英寸分辨率
        public static int getJpgSize(string FileName, out Size JpgSize, out float Wpx, out float Hpx)
        {
            //C#快速获取JPG图片大小及英寸分辨率
            JpgSize = new Size(0, 0);
            Wpx = 0; Hpx = 0;
            int rx = 0;
            if (!File.Exists(FileName)) return rx;
            FileStream F_Stream = File.OpenRead(FileName);
            int ff = F_Stream.ReadByte();
            int type = F_Stream.ReadByte();
            if (ff != 0xff || type != 0xd8)
            {
                //非JPG文件
                F_Stream.Close();
                return rx;
            }

            long ps = 0;
            do
            {
                do
                {
                    ff = F_Stream.ReadByte();
                    if (ff < 0) //文件结束
                    {

                        F_Stream.Close();
                        return rx;
                    }
                } while (ff != 0xff);

                do
                {
                    type = F_Stream.ReadByte();
                } while (type == 0xff);

                F_Stream.Position.ToString();
                ps = F_Stream.Position;
                switch (type)
                {
                    case 0x00:
                    case 0x01:
                    case 0xD0:
                    case 0xD1:
                    case 0xD2:
                    case 0xD3:
                    case 0xD4:
                    case 0xD5:
                    case 0xD6:
                    case 0xD7:
                        break;
                    case 0xc0:
                        //SOF0段
                        ps = F_Stream.ReadByte() * 256;
                        ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度

                        F_Stream.ReadByte();
                        //丢弃精度数据
                        //高度
                        JpgSize.Height = F_Stream.ReadByte() * 256;
                        JpgSize.Height = JpgSize.Height + F_Stream.ReadByte();
                        //宽度
                        JpgSize.Width = F_Stream.ReadByte() * 256;
                        JpgSize.Width = JpgSize.Width + F_Stream.ReadByte();

                        //后面信息忽略
                        if (rx != 1 && rx < 3) rx = rx + 1;
                        break;
                    case 0xe0:
                        //APP0段
                        ps = F_Stream.ReadByte() * 256;
                        ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度

                        F_Stream.Seek(5, SeekOrigin.Current);
                        //丢弃APP0标记(5bytes)
                        F_Stream.Seek(2, SeekOrigin.Current);
                        //丢弃主版本号(1bytes)及次版本号(1bytes)
                        int units = F_Stream.ReadByte();
                        //X和Y的密度单位,units=0：无单位,units=1：点数/英寸,units=2：点数/厘米

                        //水平方向(像素/英寸)分辨率
                        Wpx = F_Stream.ReadByte() * 256;
                        Wpx = Wpx + F_Stream.ReadByte();
                        if (units == 2) Wpx = (float)(Wpx * 2.54); //厘米变为英寸

                        //垂直方向(像素/英寸)分辨率
                        Hpx = F_Stream.ReadByte() * 256;
                        Hpx = Hpx + F_Stream.ReadByte();
                        if (units == 2) Hpx = (float)(Hpx * 2.54); //厘米变为英寸
                        //后面信息忽略
                        if (rx != 2 && rx < 3) rx = rx + 2;
                        break;
                    default:
                        //别的段都跳过////////////////
                        ps = F_Stream.ReadByte() * 256;
                        ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度
                        break;
                }
                if (ps + 1 >= F_Stream.Length) //文件结束
                {

                    F_Stream.Close();
                    return rx;
                }
                F_Stream.Position = ps; //移动指针
            } while (type != 0xda); // 扫描行开始
            F_Stream.Close();
            return rx;
        }

        #endregion 成员方法

        #region 构造函数

        public ImageCutor()
        {
            InitializeComponent();
        }

        #endregion 构造函数

        #region 处理方法

        public void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)
        {

            ContentControl image = sender as ContentControl;
            if (image == null)
            {
                return;
            }

            TransformGroup group = ImageComparePanel.FindResource("ImageCompareResources") as TransformGroup;
            Debug.Assert(group != null, "Can't find transform group from image compare panel resource");
            Point point = e.GetPosition(image);
            double scale = e.Delta * 0.001;
            ZoomImage(group, point, scale);
        }

        private static void ZoomImage(TransformGroup group, Point point, double scale)
        {
            Debug.Assert(group != null, "Oops, ImageCompareResources is removed from current control's resouce");

            Point pointToContent = group.Inverse.Transform(point);
            ScaleTransform transform = group.Children[0] as ScaleTransform;

            if (transform.ScaleX + scale < 0.5)
            {
                return;
            }

            transform.ScaleX += scale;
            transform.ScaleY += scale;
            TranslateTransform transform1 = group.Children[1] as TranslateTransform;
            transform1.X = -1 * ((pointToContent.X * transform.ScaleX) - point.X);
            transform1.Y = -1 * ((pointToContent.Y * transform.ScaleY) - point.Y);
        }

        public void MasterImage_MouseMove(object sender, MouseEventArgs e)
        {
            ContentControl image = sender as ContentControl;

            if (image == null)
            {
                return;
            }

            if (this.isMouseLeftButtonDown && e.LeftButton == MouseButtonState.Pressed)
            {
                this.DoImageMove(image, e.GetPosition(image));
            }
        }

        private void DoImageMove(ContentControl image, Point position)
        {

            TransformGroup group = ImageComparePanel.FindResource("ImageCompareResources") as TransformGroup;

            Debug.Assert(group != null, "Can't find transform group from image compare panel resource");

            TranslateTransform transform = group.Children[1] as TranslateTransform;

            transform.X += position.X - this.previousMousePoint.X;

            transform.Y += position.Y - this.previousMousePoint.Y;

            this.previousMousePoint = position;
        }

        public void MasterImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var img = sender as ContentControl;
            if (img == null) return;

            this.oldCursor = this.Cursor;
            this.Cursor = Cursors.SizeAll;

            img.CaptureMouse();
            this.isMouseLeftButtonDown = true;
            this.previousMousePoint = e.GetPosition(img);
        }

        public void MasterImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var img = sender as ContentControl;
            if (img == null) return;

            this.Cursor = this.oldCursor;

            img.ReleaseMouseCapture();
            this.isMouseLeftButtonDown = false;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var layer = AdornerLayer.GetAdornerLayer(ImageComparePanel);
            _IMAdorner = new IMAdorner(ImageComparePanel, this);
            layer.Add(_IMAdorner);
        }

        string filePath;
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount < 2) return;

            if (MasterImage.Source == null)
            {
                #region 打开本地资源

                string selectFileName;//存放所选文件的文件名

                OpenFileDialog openFileDialog = new OpenFileDialog();

                //获取电脑桌面的路径
                String Desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

                //初始化打开为电脑桌面路径
                openFileDialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory + Desktop + "\\";
                openFileDialog.Filter = "图像文件|*.png;*.jpg;*.bmp;*gif|所有文件|*.*";
                openFileDialog.RestoreDirectory = true;
                openFileDialog.FilterIndex = 1;

                if (openFileDialog.ShowDialog() == true)
                {
                    selectFileName = System.IO.Path.GetFileName(openFileDialog.FileName);//获取文件名
                    filePath = openFileDialog.FileName;//获得选择的文件路径

                    // Read byte[] from png file
                    BinaryReader binReader = new BinaryReader(File.Open(filePath, FileMode.Open));
                    FileInfo fileInfo = new FileInfo(filePath);
                    byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);
                    binReader.Close();

                    // Init bitmap
                    BitmapImage bitmap = new BitmapImage();
                    bitmap.BeginInit();
                    bitmap.StreamSource = new MemoryStream(bytes);
                    bitmap.EndInit();

                    MasterImage.Source = bitmap;
                }

                #endregion 打开本地资源
            }
            else
            {
                #region 裁剪图片

                //目标效果,即界面选取框相对于界面的坐标以及宽高，界面像素600*600
                double x1 = 125;
                double y1 = 125;
                double width1 = 350;
                double height1 = 350;

                //界面呈现效果
                TransformGroup group = ImageComparePanel.FindResource("ImageCompareResources") as TransformGroup;
                TranslateTransform transform1 = group.Children[1] as TranslateTransform;
                ScaleTransform transform = group.Children[0] as ScaleTransform;
                Point p = MasterImage.TranslatePoint(new Point(0, 0), ImageComparePanel);
                double x2 = p.X;
                double y2 = p.Y;
                //double x2 = transform1.X;
                //double y2 = transform1.Y + 75;//75是图片偏移量，通过qq截图工具比划得出
                double scaleX = transform.ScaleX;
                double scaleY = transform.ScaleY;

                //Image控件被设置成Uniform时会自动将原图缩放，此时需要求出原图与控件呈现图的缩放比例offset
                Size size;
                float wpx;
                float hpx;
                getJpgSize(filePath, out size, out wpx, out hpx);
                double offset = 1;
                if (size.Width == 0 || size.Height == 0)
                {
                    offset = MasterImage.Source.Width / MasterImage.ActualWidth;
                }
                else
                {
                    offset = size.Width / MasterImage.ActualWidth;
                }

                //计算原图的裁剪位置以及宽高
                double x = ((x1 - x2) / scaleX) * offset;
                double y = ((y1 - y2) / scaleY) * offset;
                double width = (width1 / scaleX) * offset;
                double height = (height1 / scaleY) * offset;

                //剪裁图片
                try
                {
                    var ob = System.Drawing.Image.FromFile(filePath);
                    var b = new System.Drawing.Bitmap((int)width1, (int)height1);
                    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(b);
                    System.Drawing.Rectangle resultRectangle = new System.Drawing.Rectangle(0, 0, (int)width1, (int)height1);
                    System.Drawing.Rectangle sourceRectangle = new System.Drawing.Rectangle((int)(x), (int)(y), (int)(width), (int)(height));
                    g.DrawImage(ob, resultRectangle, sourceRectangle, System.Drawing.GraphicsUnit.Pixel);
                    //GetPicThumbnail(b, @"D:\imagecutor.jpg", 95);
                    ResultImage = b;
                }
                catch (Exception)
                {
                }

                this.Close();
                #endregion 裁剪图片
            }
        }

        #endregion 处理方法
    }

    //蒙版修饰器
    class IMAdorner : Adorner
    {
        ImageCutor _parent;
        public double x1;
        public double y1;
        public double width;
        public double height;

        public IMAdorner(UIElement adorned, ImageCutor parent)
            : base(adorned)
        {
            _parent = parent;
        }

        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            Grid ic = this.AdornedElement as Grid;
            SolidColorBrush scb = new SolidColorBrush(Color.FromArgb(197, 173, 173, 173));

            x1 = ic.Width;
            y1 = ic.Height;
            width = height = (ic.Width - 100) / 2;
            dc.DrawRectangle(new SolidColorBrush(), new Pen(scb, width), new Rect(0, 0, x1, y1));
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            _parent.MasterImage_MouseLeftButtonDown(_parent.TestContentControl1, e);
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            _parent.MasterImage_MouseLeftButtonUp(_parent.TestContentControl1, e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            _parent.MasterImage_MouseMove(_parent.TestContentControl1, e);
        }

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            _parent.MasterImage_MouseWheel(_parent.TestContentControl1, e);
        }
    }
}
